package cn.fetosoft.woodpecker.core.data.base;

import com.alibaba.fastjson.annotation.JSONField;
import com.mongodb.BasicDBList;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.mapping.FieldType;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;

import java.lang.reflect.Field;
import java.util.*;

/**
 * @author guobingbing
 * @create 2020-02-27 10:23
 */
@Setter
@Getter
@Slf4j
public class BaseForm {

	/**
	 * 超始页
	 */
	@JSONField(serialize = false)
	private int page = 1;

	/**
	 * 每页记录数，默认0为查询全部
	 */
	@JSONField(serialize = false)
	private int rows = 10;

	/**
	 * 起始记录
	 */
	@JSONField(serialize = false)
	private int startRecord;

	/**
	 * 总记录数
	 */
	@JSONField(serialize = false)
	private int recordCount;

	/**
	 * 页数
	 */
	@JSONField(serialize = false)
	private int pageCount;

	/**
	 * 多参数升序字段
	 * @return
	 */
	@JSONField(serialize = false)
	private List<String> ascFields = new ArrayList<>();

	/**
	 * 多参数降序字段
	 */
	@JSONField(serialize = false)
	private List<String> descFields = new ArrayList<>();

	public int getPage() {
		if(page==0) {
			page = 1;
		}
		return page;
	}

	public int getStartRecord() {
		if(this.getPage()>0) {
			startRecord = (this.getPage() - 1) * this.getRows();
		} else {
			startRecord = 0;
		}
		return startRecord;
	}

	public int getPageCount() {
		if(recordCount>0 && getRows()>0) {
			if(recordCount%getRows()>0) {
				pageCount = recordCount / getRows() + 1;
			}else {
				pageCount = recordCount / getRows();
			}
		}
		else{
			pageCount = 1;
		}
		return pageCount;
	}

	public void setAscField(String... fields){
		this.ascFields.addAll(Arrays.asList(fields));
	}

	public void setDescField(String... fields){
		this.descFields.addAll(Arrays.asList(fields));
	}

	/**
	 * 创建查询条件
	 * @author guobingbing
	 * @date 2020/12/1 18:25
	 * @param
	 * @return org.springframework.data.mongodb.core.query.Query
	 */
	public Query buildQuery() throws Exception{
		List<Sort.Order> list=new ArrayList<>();
		Query query = new Query();
		Field[] fields = this.getClass().getDeclaredFields();
		Map<String, List<Criteria>> criteriaMap = new HashMap<>(32);
		for(Field f : fields){
			f.setAccessible(true);
			Condition condition = f.getAnnotation(Condition.class);
			Object v = f.get(this);
			if(condition!=null && v!=null){
				Criteria criteria = null;
				String fieldName = f.getName();
				if(StringUtils.isNotBlank(condition.fieldName())){
					fieldName = condition.fieldName();
				}
				if(condition.fieldType() == FieldType.STRING){
					if(StringUtils.isNotBlank(v.toString())) {
						criteria = Criteria.where(fieldName);
					}
				}else{
					criteria = Criteria.where(fieldName);
				}
				if(criteria!=null) {
					switch (condition.conditionType()) {
						case EQ:
							criteria.is(v);
							break;
						case GT:
							criteria.gt(v);
							break;
						case GTE:
							criteria.gte(v);
							break;
						case LT:
							criteria.lt(v);
							break;
						case LTE:
							criteria.lte(v);
							break;
						case LIKE:
							criteria.regex(".*?" +convertChar(v.toString())+ ".*");
							break;
						case IN:
							criteria.in((BasicDBList)v);
							break;
						default:
							break;
					}
					//新增
					if(criteriaMap.containsKey(fieldName)){
						List<Criteria> clist = criteriaMap.get(fieldName);
						clist.add(criteria);
						criteriaMap.put(fieldName, clist);
					}else{
						List<Criteria> clist = new ArrayList<>(8);
						clist.add(criteria);
						criteriaMap.put(fieldName, clist);
					}
				}
			}
		}
		//新增
		for(Map.Entry<String, List<Criteria>> entry : criteriaMap.entrySet()){
			List<Criteria> clist = criteriaMap.get(entry.getKey());
			Criteria criteria = null;
			if(clist.size()>1){
				criteria = new Criteria();
				criteria.andOperator(clist.get(0), clist.get(1));
			}else{
				criteria = clist.get(0);
			}
			query.addCriteria(criteria);
		}
		if(ascFields.size()>0){
			for (String s: ascFields) {
				list.add(Sort.Order.asc(s));
			}
			query.with(Sort.by(list));
		}
		if(descFields.size()>0){
			for (String s: descFields) {
				list.add(Sort.Order.desc(s));
			}
			query.with(Sort.by(list));
		}
		return query;
	}

	/**
	 * 特殊字符转义
	 * @return
	 */
	private String convertChar(String s){
		String ss=null;
		String filterStr="*.?+$^[](){}|\\/";
		StringBuffer sf=new StringBuffer();
		for (int i=0;i<s.length();i++){
			ss=String.valueOf(s.charAt(i));
			if(filterStr.contains(ss)){
				ss="/"+ss;
			}
			sf.append(ss);
		}
		return sf.toString();
	}
}
